package com.xbongbong.esign.helper;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.esign.comm.HttpHelper;
import com.xbongbong.esign.comm.JSONHelper;
import com.xbongbong.esign.constant.ConfigConstant;
import com.xbongbong.esign.enums.RequestType;
import com.xbongbong.esign.exception.DefineException;
import com.xbongbong.esign.param.AccountParamUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.util.URLEncodeUtils;
import com.xbongbong.pro.config.ProBaseConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @description 账号相关 辅助类
 * @author 宫清
 * @date 2019年7月20日 下午3:29:34
 * @since JDK1.7
 */
@Component
public class AccountHelper {
	@Resource
	private HttpHelper httpHelper;

	private static final Logger LOG = LoggerFactory.getLogger(AccountHelper.class);

	/**
	 * 不允许外部创建实例
	 */
	private AccountHelper() {
	}


	// --------------------------------------------------------------------------------------------------个人账号相关start-----------

	/**
	 * @description 创建个人账号
	 *
	 *              说明：
	 *              <p>
	 *              对接方调用本接口在 e 签宝平台中创建个人账号，生成的accountId请妥善保管,后续有关该用户的所有 操作都需使用该用户的
	 *              accountId。如提供用户证件信息，则将根据提供的用户证件 信息申请数字证书
	 *
	 *              <p>
	 *              组装参数：
	 *              {@link AccountParamUtil#createPersonAcctParam(String, String, String, String, String, String)}
	 *
	 * @return
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午4:22:37
	 */
	public JSONObject createPersonAcct(String thirdPartyUserId, String name, String idType, String idNumber,
			String mobile, String email) throws DefineException {

		String param = AccountParamUtil.createPersonAcctParam(thirdPartyUserId, name, idType, idNumber, mobile, email);
		JSONObject json = httpHelper.doCommHttp(RequestType.POST, ConfigConstant.createPerAcc_URL(), param);
		return JSONHelper.castDataJson(json,JSONObject.class);
	}

	/**
	 * @description 个人账号修改【 按照账号 ID】
	 *
	 *              说明：
	 *              <p>
	 *              对接方在 e 签宝平台中使用账号 id 更新个人账号，如变更姓 名，则系统根据变更后的身份信息自动申请新数字证书，
	 *              如账号已实名则会变更为未 实名状态。
	 *
	 *              <p>
	 *              组装参数：
	 *              {@link AccountParamUtil#updatePersonAcctParam(String, String, String)}
	 *
	 * @return
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午4:58:01
	 */
	public JSONObject updatePersonAcctByAcctId(String accountId, String email, String mobile, String name)
			throws DefineException {

		String param = AccountParamUtil.updatePersonAcctParam(email, mobile, name);
		JSONObject json = httpHelper.doCommHttp(RequestType.PUT, ConfigConstant.modifyPerAccById_URL(accountId), param);
		return JSONHelper.castDataJson(json,JSONObject.class);
	}

	/**
	 * @description 个人账号修改【按照第三方用户 ID】
	 *
	 *              说明：
	 *              <p>
	 *              对接方在 e 签宝平台中使用第三方用户 id 更新个人账号 ，如 变更姓名，则系统根据变更后的身份信息自动申请新数字证书，
	 *              如账号已实名则会变 更为未实名状态。
	 *
	 *              <p>
	 *              组装参数：
	 *              {@link AccountParamUtil#updatePersonAcctParam(String, String, String)}
	 *
	 * @return
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午4:58:01
	 */
	public JSONObject updatePersonAcctByThirdId(String thirdId, String email, String mobile, String name)
			throws DefineException {

		String param = AccountParamUtil.updatePersonAcctParam(email, mobile, name);
		JSONObject json = httpHelper.doCommHttp(RequestType.POST, ConfigConstant.modifyPerAccByThirdId_URL(thirdId), param);
		return JSONHelper.castDataJson(json,JSONObject.class);
	}

	/**
	 * @description 查询个人账号【按照账号ID】
	 *
	 *              说明：
	 *              <p>
	 *              使用创建账号返回的账号 id 查询用户的账号
	 *
	 * @param accountId 创建返回的账号id
	 * @return
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午5:09:49
	 */
	public JSONObject qryPersonAcctByAcctId(String accountId) throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.GET, ConfigConstant.queryAccById_URL(accountId), null);
		return JSONHelper.castDataJson(json,JSONObject.class);
	}

	/**
	 * @description 查询个人账号【按照第三方用户 ID】
	 *
	 *              说明：
	 *              <p>
	 *              当对接方创建账户时传入第三方平台的 userId 时，支持使用第三方平台的 userId 查询用户的账号
	 *
	 * @param thirdId 创建账户时传入的第三方用户id
	 * @return
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午5:09:49
	 */
	public JSONObject qryPersonAcctByThirdId(String thirdId) throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.GET, ConfigConstant.queryAccByThirdId_URL(thirdId), null);
		return JSONHelper.castDataJson(json,JSONObject.class);
	}

	/**
	 * @description 注销个人账号【按照账号 ID】
	 *
	 *              说明：
	 *              <p>
	 *              1. 通过账号 id 注销 e 签宝平台的个人账号
	 *              <p>
	 *              2. 注销后的账号不能再发起签署，已发起的流程也无法继续签署
	 *
	 * @param accountId 创建返回的账号id
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午5:13:57
	 */
	public void delPersonAcctByAcctId(String accountId) throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.DELETE, ConfigConstant.logoutAccById_URL(accountId), null);
		JSONHelper.castDataJson(json,Object.class);
	}

	/**
	 * @description 注销个人账号【按照第三方用户 ID】
	 *
	 *              说明： 当对接方创建账户时传入第三方平台的 userId 时，
	 *              <p>
	 *              1. 通过第三方平台的 userId 注销 e 签宝平台的个人账号
	 *              <p>
	 *              2. 注销后的账号不能再发起签署，但可以在已发起的流程中继续进行签署
	 *
	 * @param thirdId 创建账户时传入的第三方用户id
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午5:15:54
	 */
	public void delPersonAcctByThirdId(String thirdId) throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.DELETE, ConfigConstant.logoutAccByThirdId_URL(thirdId), null);
		JSONHelper.castDataJson(json,Object.class);
	}

	// --------------------------------------------------------------------------------------------------个人账号相关end-------------

	// --------------------------------------------------------------------------------------------------机构账号相关start-------------

	/**
	 * @description 创建机构账号
	 *
	 *              说明：
	 *              <p>
	 *              1. 对接方调用本接口在 e 签宝平台中创建机构账号，后续有关该机构的所有操作都 需使用该机构的
	 *              accountId。如提供机构证件信息，则将根据提供的机构证件信 息申请数字证书。
	 *
	 *              <p>
	 *              2. 由于机构是一个组织实体，机构账号时需要机构创建人执行，同时如该机构创建
	 *              人完成机构实名认证，则在签署和管理操作时需要由创建人执行，故在创建机构
	 *              时需要先调用{@link AccountHelper#createPersonAcct}接口完成机构创建人创建，并将机构创建人的账号
	 *              Id 传入接口
	 *
	 *              组装参数：
	 *              <p>
	 *              {@link AccountParamUtil#createOrgAcctParam(String, String, String, String, String)}
	 *
	 * @return
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午5:23:31
	 */
	public JSONObject createOrgAcct(String thirdPartyUserId, String creatorId, String name, String idType,
			String idNumber) throws DefineException {

		String param = AccountParamUtil.createOrgAcctParam(thirdPartyUserId, creatorId, name, idType, idNumber);
		JSONObject json = httpHelper.doCommHttp(RequestType.POST, ConfigConstant.createOrgAcc_URL(), param);
		return JSONHelper.castDataJson(json,JSONObject.class);
	}

	/**
	 * @description 机构账号修改【按照账号 ID】
	 *
	 *              说明：
	 *              <p>
	 *              对接方调用本接口在 e 签宝平台中使用账号 id 更新机构账号，如变更名 称后，则系统根据变更后的信息自动申请新数字证书，
	 *              如账号已实名则会变更为未实 名状态。
	 *
	 *
	 *              组装参数：
	 *              <p>
	 *              {@link AccountParamUtil#updateOrgAcct(String)}
	 * @return
	 * @author 宫清
	 * @date 2019年7月20日 下午5:43:43
	 */
	public JSONObject updateOrgAcctByOrgId(String orgId, String name) throws DefineException {
		String param = AccountParamUtil.updateOrgAcct(name);
		JSONObject json = httpHelper.doCommHttp(RequestType.PUT, ConfigConstant.modifyOrgAccById_URL(orgId), param);
		return JSONHelper.castDataJson(json,JSONObject.class);
	}

	/**
	 * @description 机构账号修改【按照第三方用户 ID】
	 *
	 *              说明：
	 *              <p>
	 *              对接方调用本接口在 e 签宝平台中使用账号 id 更新机构账号，如变更名 称后，则系统根据变更后的信息自动申请新数字证书，
	 *              如账号已实名则会变更为未实 名状态。
	 *
	 *
	 *              组装参数：
	 *              <p>
	 *              {@link AccountParamUtil#updateOrgAcct(String)}
	 * @return
	 * @author 宫清
	 * @date 2019年7月20日 下午5:43:43
	 */
	public JSONObject updateOrgAcctByThirdId(String thirdId, String name) throws DefineException {
		String param = AccountParamUtil.updateOrgAcct(name);
		JSONObject json = httpHelper.doCommHttp(RequestType.POST, ConfigConstant.modifyOrgAccByThirdId_URL(thirdId), param);
		return JSONHelper.castDataJson(json,JSONObject.class);
	}

	/**
	 * @description 查询机构账号【按照机构ID】
	 *
	 *              说明：
	 *              <p>
	 *              使用创建账号返回的账号 id 查询机构账号
	 *
	 * @param orgId 创建机构账号返回的机构ID
	 * @return
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午5:52:06
	 */
	public JSONObject qryOrgAcctByOrgId(String orgId) throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.GET, ConfigConstant.queryOrgAccById_URL(orgId), null);
		return JSONHelper.castDataJson(json,JSONObject.class);
	}

	/**
	 * @description 查询机构账号【按照第三方用户 ID】
	 *
	 *              说明：
	 *              <p>
	 *              当对接方创建账户时传入第三方平台的 userId 时，支持使用第三方平台的 userId 查询机构的账号
	 *
	 * @param thirdId 第三方平台的 userId
	 * @return
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午5:52:06
	 */
	public JSONObject qryOrgAcctByThirdId(String thirdId) throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.GET, ConfigConstant.queryOrgAccByThirdId_URL(thirdId), null);
		return JSONHelper.castDataJson(json,JSONObject.class);
	}

	/**
	 * @description 注销机构账号【按照账号 ID】
	 *
	 *              说明：
	 *              <p>
	 *              通过账号 id 注销 e 签宝平台的机构账号，注销后的账号不能再发起签署， 已发起的流程也无法继续签署
	 *
	 * @param orgId 创建机构时返回的账号
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午5:55:39
	 */
	public void delOrgAcctByOrgId(String orgId) throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.DELETE, ConfigConstant.logoutOrgAccById_URL(orgId), null);
		JSONHelper.castDataJson(json,Object.class);
	}

	/**
	 * @description 注销机构账号【按照第三方用户 ID】
	 *
	 *              说明：
	 *              <p>
	 *              通过账号 id 注销 e 签宝平台的机构账号，注销后的账号不能再发起签署， 已发起的流程也无法继续签署
	 *
	 * @param thirdId 按照第三方用户 ID
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午5:55:39
	 */
	public void delOrgAcctByThirdId(String thirdId) throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.DELETE, ConfigConstant.logoutOrgAccByThirdId_URL(thirdId),
				null);
		JSONHelper.castDataJson(json,Object.class);
	}
	// --------------------------------------------------------------------------------------------------机构账号相关end---------------

	// --------------------------------------------------------------------------------------------------静默签署设置相关start---------

	/**
	 * @description 设置静默签署
	 *
	 *              组装参数：
	 *              <p>
	 *              {@link AccountParamUtil#setAutoSignUrl(String)}
	 *
	 * @param accountId 授权人 id，即个人账 号 id 或机构账号 id
	 * @param deadLine  授权截止时间, 格式为 yyyy-MM-dd HH:mm:ss
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午6:37:37
	 */
	public void setAutoSign(String accountId, String deadLine) throws DefineException {
		String param = AccountParamUtil.setAutoSignUrl(deadLine);
		JSONObject json = httpHelper.doCommHttp(RequestType.POST, ConfigConstant.signAuth_URL(accountId), param);
		JSONHelper.castDataJson(json, Boolean.class);
	}


	/**
	 * @description 撤销静默签署
	 *
	 * @param accountId
	 * @throws DefineException
	 * @author 宫清
	 * @date 2019年7月20日 下午7:03:37
	 */
	public void revokeAutoSign(String accountId)throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.DELETE, ConfigConstant.signAuth_URL(accountId), null);
		JSONHelper.castDataJson(json, Boolean.class);
	}
	// --------------------------------------------------------------------------------------------------静默签署设置相关end-----------


	/**
	 * 套餐转售
	 * @param corpId 购买企业corpId
	 * @param orderId isv方的订单Id（用于幂等，请保证唯一性）
	 * @param itemCode 商品id
	 * @param iteName 商品名称
	 * @param quantity 购买数量
	 * @param orderCreateTime 下单时间
	 * @param payFee 支付金额（以元为单位，仅作记录，不作为凭证）
	 * @throws DefineException
	 * 创建时间 2020/7/2 8:08 PM
	 * 修改时间 2020/7/2 8:08 PM
	 * @author chy
	 */
	public JSONObject orderResale(String corpId, String orderId, String itemCode, String iteName,
								  Integer quantity, Long orderCreateTime, Float payFee)throws DefineException {
		String param = AccountParamUtil.setOrderResaleUrl(corpId, orderId, itemCode, iteName, quantity, orderCreateTime, payFee * 100);
		LOG.info("orderResale url:" + ConfigConstant.orderResale_URL());
		LOG.info("orderResale param:" + param);
		JSONObject json = httpHelper.doCommHttp(RequestType.POST, ConfigConstant.orderResale_URL(), param);
		return JSONHelper.castDataJson(json, JSONObject.class);
	}

	/**
	 * 查询套餐余量
	 * @param corpId 企业corpId
	 * @throws DefineException
	 * 创建时间 2020/7/2 8:08 PM
	 * 修改时间 2020/7/2 8:08 PM
	 * @author chy
	 */
	public JSONObject contractMargin(String corpId)throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.GET, ConfigConstant.contractMargin_URL(corpId), null);
		return JSONHelper.castDataJson(json, JSONObject.class);
	}

	/**
	 * 查询企业信息
	 * @param corpId 企业corpId
	 * @throws DefineException
	 * 创建时间 2020/7/2 8:08 PM
	 * 修改时间 2020/7/2 8:08 PM
	 * @author chy
	 */
	public JSONObject corpInfo(String corpId)throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.GET, ConfigConstant.corpInfo_URL(corpId), null);
		return JSONHelper.castDataJson(json, JSONObject.class);
	}

	/**
	 * 查询个人信息
	 * @param corpId 企业corpId
	 * @param userId 个人的userId
	 * @throws DefineException
	 * 创建时间 2020/7/2 8:08 PM
	 * 修改时间 2020/7/2 8:08 PM
	 * @author chy
	 */
	public JSONObject userInfo(String corpId, String userId)throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.GET, ConfigConstant.userInfo_URL(corpId, userId), null);
		return JSONHelper.castDataJson(json, JSONObject.class);
	}

	/**
	 * 获取跳转到个人实名的地址
	 * @param corpId 当前企业corpId
	 * @param userId 当前用户userId（必须是管理员）
	 * @param redirectUrl 实名成功后重定向地址
	 * @return
	 * @throws DefineException
	 * 创建时间 2020/7/2 8:33 PM
	 * 修改时间 2020/7/2 8:33 PM
	 * @author chy
	 */
	public JSONObject userRealname(String corpId, String userId, String redirectUrl)throws DefineException {
		String param = AccountParamUtil.setCorpRealnameUrl(corpId, userId, redirectUrl);
		JSONObject json = httpHelper.doCommHttp(RequestType.POST, ConfigConstant.userRealname_URL(), param);
		return JSONHelper.castDataJson(json, JSONObject.class);
	}

	/**
	 * 获取跳转到企业实名的地址
	 * @param corpId 当前企业corpId
	 * @param userId 当前用户userId（必须是管理员）
	 * @param redirectUrl 实名成功后重定向地址
	 * @return
	 * @throws DefineException
	 * 创建时间 2020/7/2 8:33 PM
	 * 修改时间 2020/7/2 8:33 PM
	 * @author chy
	 */
	public JSONObject corpRealname(String corpId, String userId, String redirectUrl)throws DefineException {
		String param = AccountParamUtil.setCorpRealnameUrl(corpId, userId, redirectUrl);
		JSONObject json = httpHelper.doCommHttp(RequestType.POST, ConfigConstant.corpRealname_URL(), param);
		return JSONHelper.castDataJson(json, JSONObject.class);
	}

	/**
	 * 获取企业控制台地址
	 * @param corpId 当前企业corpId
	 * @return
	 * @throws DefineException
	 * 创建时间 2020/7/2 8:33 PM
	 * 修改时间 2020/7/2 8:33 PM
	 * @author chy
	 */
	public JSONObject corpConsole(String corpId)throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.GET, ConfigConstant.corpConsole_URL(corpId), null);
		return JSONHelper.castDataJson(json, JSONObject.class);
	}


	/**
	 * @description 获取token
	 *
	 *              实际使用中，可获取token后，放在redis缓存中，如果是非分布式架构，也可使用guava的LoadingCache或者自己构建本地缓存来存储该token，
	 *              缓存存储时，需要注意缓存失效截止时间expiresIn
	 *
	 * @date 2019年7月19日 上午11:55:57
	 * @author 宫清
	 * @throws DefineException
	 */
	public JSONObject getCorpStatus(String corpid) throws DefineException {
		JSONObject json = httpHelper.doCommHttp(RequestType.GET,
				ConfigConstant.getCorpStatus_URL(corpid), null);
		json = JSONHelper.castDataJson(json,JSONObject.class);

		return json;

	}

	/**
	 * @description 获取token
	 *
	 *              实际使用中，可获取token后，放在redis缓存中，如果是非分布式架构，也可使用guava的LoadingCache或者自己构建本地缓存来存储该token，
	 *              缓存存储时，需要注意缓存失效截止时间expiresIn
	 *
	 * @date 2019年7月19日 上午11:55:57
	 * @author 宫清
	 * @throws DefineException
	 */
	public JSONObject getAuthUrl(String corpid, String redirectUrl) throws DefineException {
        if (!StringUtil.isEmpty(redirectUrl)) {
            redirectUrl = "dingtalk://dingtalkclient/action/openapp?corpid=" + corpid +"&container_type=work_platform&app_id=" + ProBaseConfig.getAppId() + "&redirect_type=jump&redirect_url=" + URLEncodeUtils.encodeURL(redirectUrl);
        }
		String param = AccountParamUtil.setAuthUrl(corpid, redirectUrl);

		JSONObject json = httpHelper.doCommHttp(RequestType.POST,
				ConfigConstant.getAuthUrl_URL(), param);
		json = JSONHelper.castDataJson(json,JSONObject.class);

		return json;

	}
}
